﻿using DefaulArchitecture;
using LMCWebStore.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using DefaulArchitecture.Domain;
using DefaulArchitecture.Paging;
using DefaulArchitecture.Message;

namespace LMCWebStore.Controllers
{
    public abstract class BasePagerController<T> : BaseController where T : IDomain, new()
    {
        #region Enums

        public enum PreviousAction { Create, Updade, Delete }

        #endregion

        #region Construtores

        public BasePagerController()
        {

        }

        #endregion

        #region Propriedades

        public PagerModel PagerModel
        {
            get
            {
                if (Session[Controller] == null)
                {
                    Session[Controller] = new PagerModel();
                    if (CountPerPage > 0)
                    {
                        PagerModel.ItemsPerPage = CountPerPage;
                    }
                }

                return (PagerModel)Session[Controller];
            }
        }

        public int Current { get; set; }

        private int countPerPage = 0;

        public virtual int CountPerPage { get { return countPerPage; } }

        public int Total { get; set; }

        public abstract string PartialViewName { get; }

        public abstract string Controller { get; }

        public abstract string JQuerySelector { get; }

        public abstract bool UsePager { get; }

        public abstract bool Append { get; }

        public abstract IPagerRepository<T> Repository { get; }

        public ICollection<T> Data { get; set; }

        public abstract string SeletorErrosFiltro { get; }

        public string SeletorErrosPaginação { get { return string.Format("{0} {1}", JQuerySelector, "#ErroList"); } }

        #endregion

        #region Métodos

        public ActionResult List()
        {
            try
            {
                Pager<T> p = new Pager<T>();
                p.Filter = new T();
                p.PageSize = PagerModel.ItemsPerPage;
                p.PageNumber = 1;
                this.Data = this.Repository.Select(p).List;

                PagerModel.TotalItems = p.TotalItems;
                PagerModel.Current = 1;
                PagerModel.Controller = this.Controller;
                PagerModel.Filter = p.Filter;

                StringBuilder sb = GetPaginationPatial();
                return new ContentResult() { ContentType = "Text/html", Content = sb.ToString(), ContentEncoding = Encoding.UTF8 };
            }
            catch (Exception ex)
            {
                this.Messages = new UIMessage(ex);
                if (Request.IsAjaxRequest())
                {
                    return new JsonError("UIMessage", this.Messages, JQuerySelector, this.ControllerContext);
                }
                else
                {
                    return PartialView("UIMessage", Messages);
                }

            }
        }

        public ActionResult Filter(T filter)
        {
            try
            {
                Pager<T> p = new Pager<T>();
                p.Filter = filter;
                p.PageSize = PagerModel.ItemsPerPage;
                p.PageNumber = 1;
                this.Data = this.Repository.Select(p).List;

                PagerModel.TotalItems = p.TotalItems;
                PagerModel.Current = 1;
                PagerModel.Controller = this.Controller;
                PagerModel.Filter = p.Filter;

                StringBuilder sb = GetPaginationPatial();

                return new JsonPartial(sb.ToString(), this.JQuerySelector, Append);
            }
            catch (Exception ex)
            {
                this.Messages = new UIMessage(ex);
                return new JsonError("UIMessage", this.Messages, this.SeletorErrosFiltro, this.ControllerContext);
            }
        }

        public virtual ActionResult FilterParams(object filter)
        {
            throw new NotImplementedException("Para utilizar esta action, sobreescreva ela no seu controller");
        }

        protected StringBuilder GetPaginationPatial()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(BaseController.RenderPartialToString(PartialViewName, Data, this.ControllerContext));
            if (UsePager && this.Data.Count > 0)
                sb.Append(BaseController.RenderPartialToString(PagerModel.PagerPartialViewName, PagerModel, this.ControllerContext));
            return sb;
        }

        public ActionResult Pager(int Index)
        {
            try
            {
                Pager<T> p = new Pager<T>();
                p.PageSize = PagerModel.ItemsPerPage;
                p.PageNumber = Index;
                p.Filter = PagerModel.Filter == null ? new T() : PagerModel.Filter;

                this.Data = this.Repository.Select(p).List;

                PagerModel.Current = Index;
                PagerModel.TotalItems = p.TotalItems;
                PagerModel.Controller = this.Controller;

                StringBuilder sb = GetPaginationPatial();

                return new JsonPartial(sb.ToString(), this.JQuerySelector, Append);

            }
            catch (Exception ex)
            {
                this.Messages = new UIMessage(ex);
                return new JsonError("UIMessage", this.Messages, this.SeletorErrosPaginação, this.ControllerContext);
            }
        }

        public ActionResult Order(string guid)
        {
            try
            {
                return null;
            }
            catch (Exception ex)
            {
                this.Messages = new UIMessage(ex);
                return new JsonError("UIMessage", this.Messages, this.SeletorErrosPaginação, this.ControllerContext);
            }
        }

        public ActionResult Clear(string guid)
        {
            try
            {
                Session[Controller] = null;
                return new JsonPartial((List() as ContentResult).Content, this.JQuerySelector, false);
            }
            catch (Exception ex)
            {
                this.Messages = new UIMessage(ex);
                return new JsonError("UIMessage", this.Messages, this.SeletorErrosPaginação, this.ControllerContext);
            }
        }

        public string RefreshList(PreviousAction action)
        {
            var p = new Pager<T>();
            p.PageSize = PagerModel.ItemsPerPage;

            switch (action)
            {
                case PreviousAction.Create:
                    PagerModel.Current = 1;
                    p.Filter = PagerModel.Filter == null ? new T() : PagerModel.Filter;
                    break;

                case PreviousAction.Updade:
                    p.PageNumber = PagerModel.Current;
                    p.Filter = PagerModel.Filter == null ? new T() : PagerModel.Filter;
                    break;

                case PreviousAction.Delete:
                    p.PageNumber = PagerModel.Current;
                    p.Filter = PagerModel.Filter == null ? new T() : PagerModel.Filter;
                    this.Data = this.Repository.Select(p).List;

                    // se o ultimo de uma pagina foi excluído, eu faço a listagem a partir da página anterior
                    if (PagerModel.Current > 1 && Data.Count() == 0)
                    {
                        this.PagerModel.Current = this.PagerModel.Current - 1;
                        p.PageNumber = PagerModel.Current;
                    }

                    break;
                default:
                    break;
            }

            this.Data = this.Repository.Select(p).List;

            PagerModel.TotalItems = p.TotalItems;
            PagerModel.Controller = this.Controller;

            StringBuilder sb = GetPaginationPatial();

            return sb.ToString();

        }

        #endregion
    }
}